package com.friendsoft.crm.bean;

import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.Query;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.friendsoft.crm.entity.Contact;
import com.friendsoft.crm.entity.User;
import com.friendsoft.crm.enumeration.State;
import com.friendsoft.crm.exception.NoEntityFoundException;

@Stateless
public class UserBean extends BaseEntityBean<User> {
	Logger logger = LoggerFactory.getLogger(UserBean.class);

	@EJB
	private ContactBean contactBean ;

	/**
	 * @param contactBean the contactBean to set
	 */
	public void setContactBean(ContactBean contactBean) {
		this.contactBean = contactBean;
	}

	private User makeUserParam(User user) {
		User userParam = new User();
		userParam.setId(user.getId());
		userParam.setUsername(user.getUsername());
		userParam.setPassword(user.getPassword());
		return userParam;
	}

	/**
	 * create a user and a contact which belongs to that user accordingly
	 * @param user
	 * @return user after getting persisted
	 */
	public User createUser(User user) {
		User persistingUser = makeUserParam(user);
		persist(persistingUser);
		if(CollectionUtils.isEmpty(user.getContacts())) {
			Contact mainContact = new Contact() ;
			mainContact.setIsMainContact(true);
			mainContact.setUser(persistingUser);
			contactBean.createContact(mainContact) ;
		} else {
			boolean isMainContact = false;
			for(Contact contact: user.getContacts()) {
				if(!isMainContact) {
					contact.setIsMainContact(true);
					isMainContact = true;
				}
				contact.setUser(persistingUser);
				contactBean.createContact(contact);
			}
		}

		return findUserById(persistingUser.getId()) ;
	}

	/**
	 * update a user
	 * @param user
	 * @return user after getting updated
	 * @throws NoEntityFoundException
	 */
	public User updateUser(User user) throws NoEntityFoundException {
		if(find(user.getId()) == null) {
			throw new NoEntityFoundException() ;
		}
		merge(user);
		return user ;
	}

	/**
	 * find a user by that user's id
	 * @param id
	 * @return user from database
	 */
	public User findUserById(long id) {
		return find(id) ;
	}

	@SuppressWarnings("unchecked")
	public User findUserByUsernameAndPassword(String username, String password) {
		if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
			logger.error("The username and password should not be empty");
			return null;
		}

		String queryStr = "SELECT u FROM User u WHERE u.username = :username AND u.password = :password";
		Query query = getEm().createQuery(queryStr);
		query.setParameter("username", username);
		query.setParameter("password", password);
		List<User> users = query.getResultList();
		if(CollectionUtils.isEmpty(users)) {
			return null;
		}
		return users.get(0);
	}

	/**
	 * get the main contact of a user
	 * @param user
	 * @return main user's contact
	 */
	public Contact getMainContact(User user) {
		if(user == null || user.getContacts() == null) {
			return null ;
		}

		for(Contact contact : user.getContacts()) {
			if(BooleanUtils.isTrue(contact.isMainContact())) {
				return contact ;
			}
		}

		return null ;
	}

	/**
	 * delete user by user's id
	 * just mark the state of this user's state as DELETED , will not delete physically
	 * @param id
	 * @return updated entity
	 * @throws NoEntityFoundException
	 */
	public User deleteUserById(long id) throws NoEntityFoundException {
		User user = find(id) ;
		if(user == null) {
			throw new NoEntityFoundException("cannot find user with id " + id) ;
		}
		user.setState(State.DELETED);
		getMainContact(user).setState(State.DELETED);
		merge(user);
		return user ;
	}
}
